package com.syys.privacy.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.TextRange;
import com.syys.common.utils.StringUtils;
import com.syys.privacy.annotation.ParagraphField;
import com.syys.privacy.domain.QaAnswer;
import com.syys.privacy.service.IQaAnswerService;

import java.awt.*;
import java.lang.reflect.Field;
import java.util.List;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author ys
 * @Classname PrivacyWordUtil
 * @Description 隐私问卷 - word 工具类
 * @Date 2021/7/19 16:38
 * @Created by ys
 */
public class PrivacyWordUtil {

    private static String[] cnArr = new String[]{"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一"};
    private static String[] roundArr = new String[]{"（1）", "（2）", "（3）", "（4）", "（5）", "（6）", "（7）", "（8）", "（9）", "（10）", "（11）", "（12）", "（13）"};
    private static IQaAnswerService iQaAnswerService;

    public static ThreadLocal<Integer> serialNumLocal = new ThreadLocal<>();
    private static Map<String, Integer> smallNumMap = new HashMap<>();
    private static List<String> radioList = new ArrayList<>();
    private static Map<String, String> checkMap = new HashMap<>();
    private static Map<String, String> inputMap = new HashMap<>();


    public static void setiQaAnswerService(IQaAnswerService iQaAnswerService) {
        PrivacyWordUtil.iQaAnswerService = iQaAnswerService;
    }

    private static void initField(Class clazz, Object obj) throws IllegalAccessException {
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        for (Field field : tempFields) {
            if (field.isAnnotationPresent(ParagraphField.class)) {
                ParagraphField annotation = field.getAnnotation(ParagraphField.class);
                if (annotation == null) {
                    continue;
                }
                String fieldName = field.getName();
                if (fieldName.indexOf("Radio") >= 0) {
                    fieldName = fieldName.substring(0, fieldName.lastIndexOf("Radio"));
                }
                field.setAccessible(true);
                String fieldValue = Objects.toString(field.get(obj), "");
                if (StringUtils.isEmpty(fieldValue)) {
                    continue;
                }
                if (annotation.type() == ParagraphField.Type.RADIO) {
                    if ("1".equals(fieldValue)) {
                        radioList.add(fieldName);
                    } else {
                        radioList.add(fieldName + "No");
                    }
                } else if (annotation.type() == ParagraphField.Type.CHECK) {
                    checkMap.put(fieldName, Objects.toString(fieldValue, null));
                } else if (annotation.type() == ParagraphField.Type.INPUT) {
                    inputMap.put(fieldName.substring(0, fieldName.lastIndexOf("Other")), Objects.toString(fieldValue, null));
                }
            }
        }
    }


    public static Optional<Document> autoGenerate(Object obj, Class clazz, String chapter, List<ParagraphDesc> paragraphDescs) throws IllegalAccessException {
        smallNumMap = new HashMap<>();
        radioList = new ArrayList<>();
        checkMap = new HashMap<>();
        inputMap = new HashMap<>();

        if (obj != null && clazz != null) {
            initField(clazz, obj);
        }
        radioList.add(chapter);
        radioList.add("chapterStatic");

        List<ParagraphDesc> paragraphDescList = paragraphDescs.stream()
                .filter(paragraphDesc -> radioList.indexOf(paragraphDesc.getUniqueFiled()) >= 0)
                .collect(Collectors.toList());

        if (paragraphDescList.size() == 0) {
            return Optional.empty();
        }

        Document document = new Document();
        Section section = document.addSection();
        paragraphDescList.forEach(paragraphDesc -> {
            if (ParagraphType.TITLE.equals(paragraphDesc.getParagraphType())) {
                Paragraph paragraphTemp = section.addParagraph();
                String serialNum = "";

                if ("chapter".equals(paragraphDesc.getSerialNumGroup())) {
                    if (serialNumLocal.get() == null) {
                        serialNumLocal.set(1);
                    }
                    serialNumLocal.set(serialNumLocal.get() + 1);
                    serialNum = paragraphDesc.isConvertChar() ? cnArr[serialNumLocal.get() - 1] + "." : serialNumLocal.get() + ".";
                } else {
                    if (smallNumMap.containsKey(paragraphDesc.getSerialNumGroup())) {
                        smallNumMap.put(paragraphDesc.getSerialNumGroup(), smallNumMap.get(paragraphDesc.getSerialNumGroup()) + 1);
                    } else {
                        smallNumMap.put(paragraphDesc.getSerialNumGroup(), 1);
                    }
                    serialNum = paragraphDesc.isConvertChar() ? cnArr[smallNumMap.get(paragraphDesc.getSerialNumGroup()) - 1] + "." : smallNumMap.get(paragraphDesc.getSerialNumGroup()) + ".";
                }

                String content = paragraphDesc.getContent();
                // 替换目标值
                content = replaceContent(paragraphDesc, content);
                TextRange textRangeTemp = paragraphTemp.appendText(serialNum + content);

                // 样式设置
                paragraphTemp.getFormat().setFirstLineIndent(paragraphDesc.getFirstLineIndent());
                textRangeTemp.getCharacterFormat().setFontSize(paragraphDesc.getFontSize());
                textRangeTemp.getCharacterFormat().setFontName(paragraphDesc.getFontName());
                textRangeTemp.getCharacterFormat().setBold(paragraphDesc.isBold());

                if (StringUtils.isNotEmpty(paragraphDesc.getBoldContent())) {
                    String[] boldContents = paragraphDesc.getBoldContent();
                    for (String boldContent : boldContents) {
                        TextSelection textSelection = paragraphTemp.find(Pattern.compile(boldContent));
                        textSelection.getAsOneRange().getCharacterFormat().setBold(true);
                    }
                }
            } else if (ParagraphType.CONTENT.equals(paragraphDesc.getParagraphType())) {
                Paragraph paragraphTemp = section.addParagraph();
                String content = paragraphDesc.getContent();
                String serialNum = "";
                if (!"default".equals(paragraphDesc.getSerialNumGroup())) {
                    if (smallNumMap.containsKey(paragraphDesc.getSerialNumGroup())) {
                        smallNumMap.put(paragraphDesc.getSerialNumGroup(), smallNumMap.get(paragraphDesc.getSerialNumGroup()) + 1);
                    } else {
                        smallNumMap.put(paragraphDesc.getSerialNumGroup(), 1);
                    }
                    serialNum = roundArr[smallNumMap.get(paragraphDesc.getSerialNumGroup()) - 1];
                }

                // 替换目标值
                content = replaceContent(paragraphDesc, serialNum + content);
                TextRange textRangeTemp = paragraphTemp.appendText(content);

                // 样式设置
                paragraphTemp.getFormat().setFirstLineIndent(paragraphDesc.getFirstLineIndent());
                textRangeTemp.getCharacterFormat().setFontSize(paragraphDesc.getFontSize());
                textRangeTemp.getCharacterFormat().setFontName(paragraphDesc.getFontName());
                textRangeTemp.getCharacterFormat().setBold(paragraphDesc.isBold());
                paragraphTemp.getFormat().setBeforeAutoSpacing(false);
                paragraphTemp.getFormat().setBeforeSpacing(1);
                paragraphTemp.getFormat().setAfterAutoSpacing(false);
                paragraphTemp.getFormat().setAfterSpacing(1);

                if (StringUtils.isNotEmpty(paragraphDesc.getBoldContent())) {
                    String[] boldContents = paragraphDesc.getBoldContent();
                    for (String boldContent : boldContents) {
                        TextSelection textSelection = paragraphTemp.find(Pattern.compile(boldContent));
                        textSelection.getAsOneRange().getCharacterFormat().setBold(true);
                    }
                }
            } else if (ParagraphType.CONTENT_FOR.equals(paragraphDesc.getParagraphType())) {
                String uniqueFiled = paragraphDesc.getUniqueFiled();
                if (uniqueFiled.lastIndexOf("No") > 0) {
                    uniqueFiled = uniqueFiled.substring(0, uniqueFiled.lastIndexOf("No"));
                }
                if (uniqueFiled.lastIndexOf("Other") > 0) {
                    uniqueFiled = uniqueFiled.substring(0, uniqueFiled.lastIndexOf("Other"));
                }
                String inputContent = inputMap.get(uniqueFiled);
                JSONArray inputJsonArr = JSONArray.parseArray(inputContent);
                inputJsonArr.forEach(input -> {
                    Paragraph paragraphTemp = section.addParagraph();
                    String content = paragraphDesc.getContent();
                    String serialNum = "";
                    if (!"default".equals(paragraphDesc.getSerialNumGroup())) {
                        if (smallNumMap.containsKey(paragraphDesc.getSerialNumGroup())) {
                            smallNumMap.put(paragraphDesc.getSerialNumGroup(), smallNumMap.get(paragraphDesc.getSerialNumGroup()) + 1);
                        } else {
                            smallNumMap.put(paragraphDesc.getSerialNumGroup(), 1);
                        }
                        serialNum = roundArr[smallNumMap.get(paragraphDesc.getSerialNumGroup()) - 1];
                    }
                    content = serialNum + content;
                    if(input instanceof JSONObject){
                        JSONObject inputJson = (JSONObject) input;
                        for (Map.Entry<String, Object> m : inputJson.entrySet()) {
                            content = content.replaceAll("【" + m.getKey() + "】", Objects.toString(m.getValue(), ""));
                        }
                    } else {
                        content = content + input;
                        if(content.lastIndexOf('；') <= 0 || content.lastIndexOf('。') <= 0){
                            content += "；";
                        }
                    }

                    TextRange textRangeTemp = paragraphTemp.appendText(content);

                    // 样式设置
                    paragraphTemp.getFormat().setFirstLineIndent(paragraphDesc.getFirstLineIndent());
                    textRangeTemp.getCharacterFormat().setFontSize(paragraphDesc.getFontSize());
                    textRangeTemp.getCharacterFormat().setFontName(paragraphDesc.getFontName());
                    textRangeTemp.getCharacterFormat().setBold(paragraphDesc.isBold());
                    paragraphTemp.getFormat().setBeforeAutoSpacing(false);
                    paragraphTemp.getFormat().setBeforeSpacing(1);
                    paragraphTemp.getFormat().setAfterAutoSpacing(false);
                    paragraphTemp.getFormat().setAfterSpacing(1);

                    if (StringUtils.isNotEmpty(paragraphDesc.getBoldContent())) {
                        String[] boldContents = paragraphDesc.getBoldContent();
                        for (String boldContent : boldContents) {
                            TextSelection textSelection = paragraphTemp.find(Pattern.compile(boldContent));
                            textSelection.getAsOneRange().getCharacterFormat().setBold(true);
                        }
                    }
                });
            } else if (ParagraphType.TABLE.equals(paragraphDesc.getParagraphType())) {
                if (paragraphDesc.getFunction() == null) {
                    return;
                }
                Map<String, Object> dataMap = (Map<String, Object>) paragraphDesc.getFunction().apply(obj);
                String[] header = (String[]) dataMap.get("header");
                List<List<String>> data = (List<List<String>>) dataMap.get("data");
                String title = (String) StringUtils.nvl(dataMap.get("title"), "");
                int beginIndex = 0;
                if (StringUtils.isNotEmpty(title)) {
                    beginIndex = 1;
                }

                Table table = section.addTable(true);
                table.getTableFormat().isBreakAcrossPages(false);
                table.resetCells(data.size() + 1 + beginIndex, header.length);
                table.getTableFormat().setLeftIndent(paragraphDesc.getFirstLineIndent());
                if (StringUtils.isNotEmpty(title)) {
                    TableRow row = table.getRows().get(0);
                    //将表格居中对齐（或设置为靠左或靠右）
                    table.getTableFormat().setHorizontalAlignment(RowAlignment.Center);
                    row.isHeader(true);
                    row.setHeightType(TableRowHeightType.Exactly);
                    row.getRowFormat().setBackColor(Color.gray);
                    row.getCells().get(0).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
                    Paragraph p = row.getCells().get(0).addParagraph();
                    p.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                    TextRange range1 = p.appendText(title);
                    range1.getCharacterFormat().setFontName(paragraphDesc.getFontName());
                    range1.getCharacterFormat().setFontSize(paragraphDesc.getFontSize());
                    range1.getCharacterFormat().setBold(paragraphDesc.isBold());
                    table.applyHorizontalMerge(0, 0, header.length - 1);
                }

                TableRow row = table.getRows().get(beginIndex);
                //将表格居中对齐（或设置为靠左或靠右）
                table.getTableFormat().setHorizontalAlignment(RowAlignment.Center);
                row.isHeader(true);
                row.setHeightType(TableRowHeightType.Exactly);
                row.getRowFormat().setBackColor(Color.gray);
                for (int i = 0; i < header.length; i++) {
                    row.getCells().get(i).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
                    Paragraph p = row.getCells().get(i).addParagraph();
                    p.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                    TextRange range1 = p.appendText(header[i]);
                    range1.getCharacterFormat().setFontName(paragraphDesc.getFontName());
                    range1.getCharacterFormat().setFontSize(paragraphDesc.getFontSize());
                    range1.getCharacterFormat().setBold(paragraphDesc.isBold());
                }

                for (int r = 0; r < data.size(); r++) {
                    TableRow dataRow = table.getRows().get(r + 1 + beginIndex);
//                    dataRow.setHeight(25);
                    dataRow.setHeightType(TableRowHeightType.Exactly);
                    dataRow.getRowFormat().setBackColor(Color.white);
                    List<String> dataRowList = data.get(r);
                    if (dataRowList.size() == 1) {
                        table.applyHorizontalMerge(r + 1 + beginIndex, 0, header.length - 1);
                    }
                    for (int c = 0; c < dataRowList.size(); c++) {
                        dataRow.getCells().get(c).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
                        Paragraph paragraph = dataRow.getCells().get(c).addParagraph();
                        paragraph.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                        TextRange range2 = paragraph.appendText(dataRowList.get(c));
                        range2.getCharacterFormat().setFontName(paragraphDesc.getFontName());
                        range2.getCharacterFormat().setFontSize(paragraphDesc.getFontSize());
                    }
                }
            }
        });

//        coverBold(document, BoldContent.PERSONAL_PROPERTY_INFORMATION);
//        coverBold(document, BoldContent.PERSONAL_HEALTH_AND_PHYSIOLOGICAL_INFORMATION);
//        coverBold(document, BoldContent.PERSONAL_BIOMETRIC_INFORMATION);
//        coverBold(document, BoldContent.PERSONALLY_IDENTIFIABLE_INFORMATION);
//        coverBold(document, BoldContent.NETWORK_IDENTITY_INFORMATION);
//        coverBold(document, BoldContent.OTHER_INFORMATION);
        return Optional.of(document);
    }

    private static String replaceContent(ParagraphDesc paragraphDesc, String content) {
        String uniqueFiled = paragraphDesc.getUniqueFiled();
        if (uniqueFiled.lastIndexOf("No") > 0) {
            uniqueFiled = uniqueFiled.substring(0, uniqueFiled.lastIndexOf("No"));
        }
        String checkMark = checkMap.get(uniqueFiled);

        List<String> collect = new ArrayList<>();
        if (StringUtils.isNotEmpty(paragraphDesc.getReplace())) {
            if (StringUtils.isNotEmpty(checkMark) && StringUtils.isNotEmpty(paragraphDesc.getReplace())) {
                List<String> accountRegisterLoginList = Arrays.asList(checkMark.split(","));
                List<QaAnswer> qaAnswers = iQaAnswerService.selectByCode(accountRegisterLoginList, uniqueFiled);
                collect = qaAnswers.stream().map(QaAnswer::getValue).collect(Collectors.toList());
            }
            String inputContent = inputMap.get(uniqueFiled);
            if (StringUtils.isNotEmpty(inputContent)) {
                collect.add(inputContent);
            }
            String contentText = StringUtils.join(collect, "、");
            content = content.replaceAll(paragraphDesc.getReplace(), contentText);
        }
        return content;
    }

    private static void coverBold(Document document, String[] fields) {
        Arrays.stream(fields).forEach(field -> {
            TextSelection[] textSelections = document.findAllString(field, false, false);
            if (textSelections != null) {
                for (TextSelection selection : textSelections) {
                    selection.getAsOneRange().getCharacterFormat().setBold(true);
                }
            }
        });
    }

    public static void copyDocument(Document document, Optional<Document> optionalDocument) {
        optionalDocument.ifPresent(sourcedDocument -> {
            for (int i = 0; i < sourcedDocument.getSections().getCount(); i++) {
                Section sectionTemp = sourcedDocument.getSections().get(i);
                for (int j = 0; j < sectionTemp.getBody().getChildObjects().getCount(); j++) {
                    Object object = sectionTemp.getBody().getChildObjects().get(j);

                    //复制文档1中的正文内容添加到文档2
                    document.getSections().get(0).getBody().getChildObjects().add(((DocumentObject) object).deepClone());
                }
            }
        });
    }

}
